package com.coocaa.x.service;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.IBinder;
import android.os.Looper;

import com.coocaa.x.framework.utils.LiteHandlerThread;
import com.coocaa.x.framework.utils.LogUtils;
import com.coocaa.x.service.litecache.aidl.ILiteCacheService;
import com.coocaa.x.service.liteccconnector.aidl.ILiteCCConnectorService;
import com.coocaa.x.service.liteconfig.aidl.ILiteConfigService;
import com.coocaa.x.service.litedb.aidl.ILiteDBService;
import com.coocaa.x.service.litedownloader.aidl.IDownloaderService;
import com.coocaa.x.service.liteplayer.aidl.ILitePlayerClientService;
import com.coocaa.x.service.liteplayer.aidl.ILitePlayerKernelProxyService;
import com.coocaa.x.service.litepm.aidl.ILitePMService;
import com.coocaa.x.service.liteservice.LiteServiceManager;
import com.coocaa.x.service.liteuser.aidl.ILiteUserService;

import java.util.List;

/**
 * TODO App统一资源入口
 *
 * @author lu
 * @version 2015年4月15日
 */
public class XServiceManager {
    public static abstract class XServiceConnection<T> implements ServiceConnection {
//        private static Map<String, String> serviceMap = new HashMap<String, String>();
//
//        static {
//// parser assert xml
//            //test
//            {
//                serviceMap.put("LiteCache", "com.coocaa.x.service.litecache2");
//                serviceMap.put("LiteCCConnector", "com.coocaa.x.service.liteccconnecter2");
//                serviceMap.put("LiteConfig", "com.coocaa.x.service.liteconfig2");
//                serviceMap.put("LiteDaemon", "com.coocaa.x.service.litedaemon2");
//                serviceMap.put("LiteDB", "com.coocaa.x.service.litedb2");
//                serviceMap.put("LiteDownloader", "com.coocaa.x.service.litedownloader");
//                serviceMap.put("LitePlayerClient", "com.coocaa.x.service.liteplayerclient2");
//                serviceMap.put("LitePlayerKernel", "com.coocaa.x.service.liteplayerkernel2");
//                serviceMap.put("LitePM", "com.coocaa.x.service.litepm2");
//                serviceMap.put("LiteEntry", "com.coocaa.x.service.liteentry");
//            }
//        }
//
//        protected static String getServiceAction(String tag) {
//            synchronized (serviceMap) {
//                return serviceMap.get(tag);
//            }
//        }

        private static long init_time = System.currentTimeMillis();
        private IBinder mIBinder = null;
        protected Context mContext = null;
        protected Intent mIntent = null;

        private T service = null;

        public XServiceConnection(String action) {
            mIntent = new Intent(action);
        }

        protected String getUsedServicePackage(String action) {
            String ret = null;
            PackageManager pm = mContext.getPackageManager();
            List<ResolveInfo> list = pm.queryIntentServices(new Intent(action), 0);
            for (ResolveInfo info : list) {
                if (ret == null && info.serviceInfo.isEnabled() && info.serviceInfo.packageName.equals(mContext.getPackageName()))
                    ret = info.serviceInfo.packageName;
                if (info.serviceInfo.isEnabled() && !info.serviceInfo.packageName.equals(mContext.getPackageName()))
                    ret = info.serviceInfo.packageName;
            }
            return ret;
        }

        public final String getAction() {
            return mIntent.getAction();
        }

        public void bindService(Context context, String pkgName) {
            LiteHandlerThread.checkMainThread();
            mContext = context;
            mIntent.setPackage(pkgName);
            LogUtils.i("entry", "bindService action:" + getAction() + "    usedPkgName:" + pkgName);
            try {
                mContext.startService(mIntent);
                mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE);
//                synchronized (this) {
//                    if (mIBinder == null)
//                        try {
//                            wait();
//                        } catch (InterruptedException e) {
//                        }
//                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

//        public final void bindService(Context context) {
//            mContext = context;
//            bindService(mContext, getUsedServicePackage(getAction()));
//        }

        public void unbindService(Context context) {
            LiteHandlerThread.checkMainThread();
//            LogUtils.i("UUUU", "unbindService action:" + getAction() + "    usedPkgName:" + mIntent.getPackage());
            mContext = context;
            try {
                mContext.unbindService(this);
                context.stopService(mIntent);
                service = null;
//                synchronized (this) {
//                    if (mIBinder != null)
//                        try {
//                            wait();
//                        } catch (InterruptedException e) {
//                        }
//                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder s) {
//            LogUtils.i("entry", "onServiceConnected " + mIntent.getAction() + " ComponentName " + name);
            synchronized (this) {
                mIBinder = s;
                notifyAll();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
//            LogUtils.i("entry", "onServiceDisconnected " + mIntent.getAction() + " ComponentName " + name);
            synchronized (this) {
                service = null;
                mIBinder = null;
                notifyAll();
            }
            // bind(mContext);
        }

        public final IBinder getIBinder() {
            synchronized (this) {
                if (mIBinder == null)
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                return mIBinder;
            }
        }

        public final T getService() {

            if (service == null)
                service = _getService();
            if ((service != null) && (Looper.getMainLooper() == Looper.myLooper())
                    && (System.currentTimeMillis() - init_time < 1000)) {
                try {
                    throw new RuntimeException("Do not call X.getService on main thread!!!!");
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(0);
                }
            }
            while (service == null) {
                service = _getService();
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return service;
        }

        public String getPackageName() {
            return mIntent.getPackage();
        }

        public final boolean isAlive() {
            return (mIBinder != null) && mIBinder.isBinderAlive();
        }

        protected abstract T _getService();
    }

    public static void init(final Context context) {
//        IntentFilter filter = new IntentFilter();
//        filter.addAction(LiteServiceManager.LITE_SERVICE_ON_CREATE_BROADCAST_ACTION);
//        context.registerReceiver(receiver, filter);
        LiteServiceManager.bind(context);
    }

    public static void uninit(Context context) {
        LiteServiceManager.unbind(context);
    }

    public static ILiteCacheService getLiteCacheService() {
        try {
            return LiteServiceManager.getILiteService().getCacheService();
        } catch (Exception e) {
            return null;
        }
    }

    public static ILiteDBService getLiteDBService() {
        try {
            return LiteServiceManager.getILiteService().getDBService();
        } catch (Exception e) {
            return null;
        }
    }

    public static ILiteCCConnectorService getLiteCCConnectorService() {
        try {
            return LiteServiceManager.getILiteService().getCCConnectorService();
        } catch (Exception e) {
            return null;
        }
    }

    public static ILiteUserService getLiteUserService() {
        try {
            return LiteServiceManager.getILiteService().getUserService();
        } catch (Exception e) {
            return null;
        }
    }

    public static ILitePMService getLitePMService() {
        try {
            return LiteServiceManager.getILiteService().getPMService();
        } catch (Exception e) {
            return null;
        }
    }

    public static ILitePlayerClientService getLitePlayerClientService() {
        try {
            return LiteServiceManager.getILiteService().getPlayerClientService();
        } catch (Exception e) {
            return null;
        }
    }

    public static ILitePlayerKernelProxyService getLitePlayerKernelProxyService() {
        try {
            return LiteServiceManager.getILiteService().getPlayerKernelProxyService();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static class RegisterService {
        public String pkgName, action;

        public RegisterService(String pkgName, String action) {
            this.pkgName = pkgName;
            this.action = action;
        }

        @Override
        public String toString() {
            return pkgName + "/" + action;
        }
    }

//    private static List<RegisterService> registerServices = new ArrayList<RegisterService>();

    public static IBinder getService(String action) {
        try {
            return LiteServiceManager.getILiteService().getService(action);
        } catch (Exception e) {
            return null;
        }
    }

    public static int registerService(String pkgName, String action) {
        try {
//            synchronized (registerServices) {
//                for (RegisterService rs : registerServices) {
//                    if (!(rs.pkgName.equals(pkgName) && rs.action.equals(action)))
//                        registerServices.add(new RegisterService(pkgName, action));
//                }
//            }
            return LiteServiceManager.getILiteService().registerService(pkgName, action);
        } catch (Exception e) {
            return -1;
        }
    }

//    private static BroadcastReceiver receiver = new BroadcastReceiver() {
//        @Override
//        public void onReceive(Context context, Intent intent) {
//            String action = intent.getAction();
//            if (action.equals(LiteServiceManager.LITE_SERVICE_ON_CREATE_BROADCAST_ACTION)) {
//                CoocaaApplication.post(new Runnable() {
//                    @Override
//                    public void run() {
//                        synchronized (registerServices) {
//                            for (RegisterService rs : registerServices) {
//                                LogUtils.d("UUUU", "LITE_SERVICE_ON_CREATE_BROADCAST_ACTION reRegService:" + rs.toString());
//                                try {
//                                    LiteServiceManager.getILiteService().registerService(rs.pkgName, rs.action);
//                                } catch (Exception e) {
//                                    e.printStackTrace();
//                                }
//                            }
//                        }
//                    }
//                });
////                String packageName = intent.getStringExtra("package");
////                if (packageName != null && packageName.equals(mContext.getPackageName()))
////                    xbind();
//            }
//        }
//    };

    public static ILiteConfigService getLiteConfigService() {
        try {
            return LiteServiceManager.getILiteService().getConfigService();
        } catch (Exception e) {
            return null;
        }
    }

    public static IDownloaderService getDownloaderService() {
        try {
            return LiteServiceManager.getILiteService().getDownloaderService();
        } catch (Exception e) {
            return null;
        }
    }
}
